package atguigu.shijiangongjulei;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalField;
import java.time.temporal.WeekFields;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.xkzhangsan.time.converter.DateTimeConverterUtil;
import com.xkzhangsan.time.formatter.DateTimeFormatterUtil;

public class DateUtil {

	public static final SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	 
	 
	public Date sevenDayDeforeBeginOfCurDay() {
        LocalDate today = LocalDate.now();
        today = today.plusDays(-6);
        return localDate2Date(today);
    }

    public Date endOfCurDay() {
        LocalDate today = LocalDate.now();
        LocalTime localTime = LocalTime.of(23, 59, 59);
        LocalDateTime localDateTime = LocalDateTime.of(today, localTime);
        return localDateTime2Date(localDateTime);
    }
    
    public static void testTimeTuiyi() {
    	Date dataLatestTiem = new Date();
    	System.out.println(dataLatestTiem);
    	Calendar calendar = Calendar.getInstance();
        calendar.setTime(dataLatestTiem);
        calendar.add(Calendar.MINUTE,5);
        Date time = calendar.getTime();
        System.out.println(time);
        
        long minBetween = getMinBetween2(dataLatestTiem, time);
        System.out.println(minBetween);
    }
    
    
    private static Date endOfDate(Date date) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
        LocalDate yesterDay = LocalDate.of(
        		calendar.get(calendar.YEAR), 
        		calendar.get(calendar.MONTH), 
        		calendar.get(calendar.DAY_OF_MONTH));
        LocalTime localTime = LocalTime.of(23, 59, 59);
        LocalDateTime localDateTime = LocalDateTime.of(yesterDay, localTime);
        return localDateTime2Date(localDateTime);
    }

    private static Date beginOfDate(Date date) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
        LocalDate yesterDay = LocalDate.of(
        		calendar.get(calendar.YEAR), 
        		calendar.get(calendar.MONTH), 
        		calendar.get(calendar.DAY_OF_MONTH));
        LocalTime localTime = LocalTime.of(0,0,0);
        LocalDateTime localDateTime = LocalDateTime.of(yesterDay, localTime);
        return localDateTime2Date(localDateTime);
    }
    
    private static Date beginOfDate(String date) {
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    	Date parse;
		try {
			parse = sdf.parse(date);
			return beginOfDate(parse);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
    }
    
    public static Date endOfDate(String date) {
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    	Date parse;
		try {
			parse = sdf.parse(date);
			return endOfDate(parse);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
    }

    public Date addDay(Date date,int day){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE,day);
		Date time = calendar.getTime();
		return time;
	}
	
	public static void main(final String[] args) {

		
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//		try {
//			Date parse = sdf.parse("2022-03-25 09:40:28");
//			Date date = new Date();
//			
//			long min = getMinBetween2(parse, date);
//			System.out.println(min);
//			
//		} catch (ParseException e) {
//			e.printStackTrace();
//		}
		
		
//		testTimeTuiyi();
		
//		Date beginOfDate = beginOfDate("2022-03-11");
//		System.out.println(beginOfDate);
//		Date endOfDate = endOfDate("2022-03-11");
//		System.out.println(endOfDate);
		
		
//		DateUtil util = new DateUtil();

//		LocalDate now = LocalDate.now();
//        int year = now.getYear();
//		for (int i = 1; i <= 31; i++) {
//            LocalDate firstday = LocalDate.of(year, 8, i);
//            Date begin = util.localDate2Date(firstday);
//            LocalTime localTime = LocalTime.of(23,59,59);
//            LocalDateTime localDateTime = LocalDateTime.of(firstday,localTime);
//            Date end = util.localDateTime2Date(localDateTime);
//            System.out.println(begin + "---"+ end);
//		}
		
		
//		Date firstDayOfCurMonth = util.beginOfCurDay();
//		System.out.println(sdf.format(firstDayOfCurMonth));
//		Date lastDayOfCurMonth = util.endOfCurDay();
//		System.out.println(sdf.format(lastDayOfCurMonth));
//		long secondBetweenCycle = util.getHourBetween(firstDayOfCurMonth,lastDayOfCurMonth);
//		System.out.println(secondBetweenCycle);
		
		
		DateUtil util = new DateUtil();
		Date begin = util.beginOfYesterDay();
		Date end = util.endOfYesterDay();
		
//		begin = util.firstDayOfCurMonth();
//		end = util.lastDayOfCurMonth();
		
		begin = util.firstDayOfCurWeek();
		end = util.lastDayOfCurWeek();

		begin = util.firstDayOfCurMonth();
		end = util.lastDayOfCurMonth();

		Integer dayBetween = util.getDayBetween(begin, end);
		System.out.println(dayBetween);

		// 30 从1-30
//		for(int i=0;i<dayBetween;i++){
//			Date date = util.addDay(begin, i);
//			Date date2 = util.endOfDay(date);
//			System.out.println(date);
//			System.out.println(date2);
//		}

		begin = util.firstDayOfCurYear();
		end = util.lastDayOfCurYear();


		dayBetween = util.getDayBetween(begin, end);
		System.out.println(dayBetween);

		Map<Integer, Integer> monthDays = util.getMonthDays();

		for(int i=1;i<=12;i++){
			Date date1 = util.firstDayOfMonth(i);
			Date date2 = util.addDay(date1,monthDays.get(i)-1);
			date2 = util.endOfDay(date2);
			System.out.println(date1);
			System.out.println(date2);
		}
//
//		dayBetween = util.getDayBetween(begin, new Date());
//		System.out.println(dayBetween-1);
//
//		Date today = new Date();
//		System.out.println(today.getMonth()+1);




		
	}

	public Date endOfDay(Date begin) {
		LocalDate today = date2localDateTime(begin).toLocalDate();
		LocalTime localTime = LocalTime.of(23, 59, 59);
		LocalDateTime localDateTime = LocalDateTime.of(today, localTime);
		return localDateTime2Date(localDateTime);
	}


	public Integer getDayBetween(Date begin, Date end) {
        if(begin != null && end != null){
            LocalDateTime localDateTime1 = date2localDateTime(begin);
            LocalDateTime localDateTime2 = date2localDateTime(end);
            Duration between = Duration.between(localDateTime1, localDateTime2);
            long l = between.toDays();
            return Math.toIntExact(l+1);
        }else{
            return 0;
        }
    }
	
	public long getHourBetween(Date begin,Date end){
        LocalDateTime ldt = end.toInstant()
                .atZone( ZoneId.systemDefault() )
                .toLocalDateTime();
        LocalTime localTime = ldt.toLocalTime();
        if(localTime.getHour() == 23
                && localTime.getMinute() == 59
                && localTime.getSecond() == 59
        ){
            long between = end.getTime()+1000 - begin.getTime();
            long hour = between / (60 * 60 * 1000);
            return hour;
        }else{
            long between = end.getTime() - begin.getTime();
            long hour = between / (60 * 60 * 1000);
            long x = between % (60 * 60 * 1000);
            long min = x / (60*1000);
            if(min == 59){
                hour +=1;
            }
            return hour;
        }
    }
	
	/**
    *
    * @param begin
    * @param end
    * @return
    */
   private long getSecondBetweenCycle(Date begin,Date end){
	// 鎴鏃堕棿鏄� 23:59:59
       LocalDateTime ldt = end.toInstant()
               .atZone( ZoneId.systemDefault() )
               .toLocalDateTime();
       LocalTime localTime = ldt.toLocalTime();
       if(localTime.getHour() == 23
               && localTime.getMinute() == 59
               && localTime.getSecond() == 59){
           long between = end.getTime()+1000 - begin.getTime();
           long s = between / 1000;
           return s;
       }else{
           long between = end.getTime() - begin.getTime();
           long s = between / 1000;
           return s;
       }
   }
   
	
	public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	public Date beginOf30Min(){
        LocalDate today = LocalDate.now();
        LocalTime time = LocalTime.now();
        time = time.plusMinutes(-30);
        LocalDateTime localDateTime = LocalDateTime.of(today,time);
        return localDateTime2Date(localDateTime);
    }

    public Date beginOf60Min() {
        LocalDate today = LocalDate.now();
        LocalTime time = LocalTime.now();
        time = time.plusMinutes(-60);
        LocalDateTime localDateTime = LocalDateTime.of(today,time);
        return localDateTime2Date(localDateTime);
    }
	
	public static long getMinBetween(Date begin, Date end) {
        long l = end.getTime() - begin.getTime();
        long day=l/(24*60*60*1000);   
        long hour=(l/(60*60*1000)-day*24);   
        long min=((l/(60*1000))-day*24*60-hour*60);   
        long s=(l/1000-day*24*60*60-hour*60*60-min*60);   
        System.out.println(""+day+"澶�"+hour+"灏忔椂"+min+"鍒�"+s+"绉�");  
        return min;
    }
	
	public static long getMinBetween2(Date begin, Date end) {
        LocalDateTime localDateTime1 = date2localDateTime(begin);
        LocalDateTime localDateTime2 = date2localDateTime(end);
        Duration between = Duration.between(localDateTime1, localDateTime2);
        return between.toMinutes();
    }

	
	public Date beginOfCurDay(){
        LocalDate today = LocalDate.now();
        LocalTime localTime = LocalTime.of(0, 0, 0);
        LocalDateTime localDateTime = LocalDateTime.of(today, localTime);
        return localDateTime2Date(localDateTime);
    }
	
	
	public Date firstDayOfCurWeek() {
        LocalDate today = LocalDate.now();
        TemporalField fieldISO = WeekFields.of(DayOfWeek.of(1), 1).dayOfWeek();
        LocalDate firstday = today.with(fieldISO, 1L);
        return localDate2Date(firstday);
    }
	
	public Date lastDayOfCurWeek() {
        LocalDate today = LocalDate.now();
        TemporalField fieldISO = WeekFields.of(DayOfWeek.of(1), 1).dayOfWeek();
        LocalDate lastDay = today.with(fieldISO, 7L);
        LocalTime localTime = LocalTime.of(23, 59, 59);
        LocalDateTime localDateTime = LocalDateTime.of(lastDay, localTime);
        return localDateTime2Date(localDateTime);
    }
	
	public Date firstDayOfCurYear() {
		LocalDate today = LocalDate.now();
		LocalDate firstday = LocalDate.ofYearDay(today.getYear(), 1);
		return localDate2Date(firstday);
	}

	public Date lastDayOfCurYear() {
		LocalDate today = LocalDate.now();
		LocalDate lastDay = today.with(TemporalAdjusters.lastDayOfYear());
		LocalTime localTime = LocalTime.of(23, 59, 59);
		LocalDateTime localDateTime = LocalDateTime.of(lastDay, localTime);
		LocalDateTime with = localDateTime.with(TemporalAdjusters.lastDayOfYear());
		return localDateTime2Date(with);
	}
	
	
	public Date beginOfYesterDay(){
        LocalDate today = LocalDate.now();
        LocalDate yesterDay = today.plusDays(-1);
        return localDate2Date(yesterDay);
    }

    public Date endOfYesterDay() {
        LocalDate today = LocalDate.now();
        LocalDate yesterDay = today.plusDays(-1);
        LocalTime localTime = LocalTime.of(23, 59, 59);
        LocalDateTime localDateTime = LocalDateTime.of(yesterDay, localTime);
        return localDateTime2Date(localDateTime);
    }
    
	public Date firstDayOfCurMonth(){
        LocalDate today = LocalDate.now();
        LocalDate firstday = LocalDate.of(today.getYear(),today.getMonth(),1);
        return localDate2Date(firstday);
    }

	public Date firstDayOfMonth(int month){
		LocalDate today = LocalDate.now();
		LocalDate firstday = LocalDate.of(today.getYear(),month,1);
		return localDate2Date(firstday);
	}

	public Date lastDayOfCurMonth() {
        LocalDate today = LocalDate.now();
        LocalDate lastDay =today.with(TemporalAdjusters.lastDayOfMonth());
        LocalTime localTime = LocalTime.of(23, 59, 59);
        LocalDateTime localDateTime = LocalDateTime.of(lastDay, localTime);
        LocalDateTime with = localDateTime.with(TemporalAdjusters.lastDayOfMonth());
        return localDateTime2Date(with);
    }



	// 05. java.time.LocalDate --> java.util.Date
	public static Date localDate2Date(LocalDate localDate) {
		ZoneId zone = ZoneId.systemDefault();
		Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
		java.util.Date date = Date.from(instant);
		return date;
	}

	public static Date localDateTime2Date(LocalDateTime localDateTime) {
		ZoneId zone = ZoneId.systemDefault();
		Instant instant = localDateTime.atZone(zone).toInstant();
		java.util.Date date = Date.from(instant);
		return date;
	}


	public static String haomiao2dateStr(long haomiao) {
		Date date = DateTimeConverterUtil.toDate(Instant.ofEpochMilli(haomiao));
		String formatToDateTimeStr = DateTimeFormatterUtil.formatToDateTimeStr(date);
		System.out.println(formatToDateTimeStr);
		return formatToDateTimeStr;
	}

	/**
	 * 閺冦儲婀￠弮鍫曟？鏉烆剚婀伴崷鎵畱閺冦儲婀￠弮鍫曟？
	 * 
	 * @param date
	 * @return
	 */
	public static LocalDateTime date2localDateTime(Date date) {
		if (date == null)
			return null;
		Instant instant = date.toInstant();
		LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
		return localDateTime;
	}

	/**
	 * 濮ｎ偆顫楁潪顒佹闂傚瓨妫╅張锟�
	 * 
	 * @param epochMilli
	 * @return
	 */
	public static Date epochMilli2date(Long epochMilli) {
		Instant ofEpochSecond = Instant.ofEpochMilli(epochMilli);
		Date date = Date.from(ofEpochSecond);
		return date;
	}

	/**
	 * 缁夋帟娴嗛弮鍫曟？閺冦儲婀�
	 * 
	 * @param epochSecond
	 * @return
	 */
	public static Date epochSecond2date(Long epochSecond) {
		Instant ofEpochSecond = Instant.ofEpochSecond(epochSecond);
		Date date = Date.from(ofEpochSecond);
		return date;
	}

	/**
	 * 閺冦儲婀℃潪顒�鐡х粭锔胯
	 * 
	 * @param date
	 * @return
	 */
	public static String date2String(Date date) {
		if (date == null)
			return "";
		LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		String format = localDate.format(formatter);
		return format;
	}

	/**
	 * 閺冦儲婀￠弮鍫曟？鏉烆剙鐡х粭锔胯
	 * 
	 * @param date
	 * @return
	 */
	public static String datetime2String(Date date) {
		if (date == null)
			return "";
		LocalDateTime localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		String format = localDate.format(formatter);
		return format;
	}

	/**
	 * 鐎涙顑佹稉鑼舵祮閺冦儲婀￠弮鍫曟？
	 * 
	 * @param str
	 * @return
	 */
	public static Date string2Date(String str) {
		if (str.length() > 10) {
			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
			LocalDateTime parse = LocalDateTime.parse(str, formatter);
			return Date.from(parse.toInstant(ZoneOffset.UTC));
		} else {
			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
			LocalDate parse = LocalDate.parse(str, formatter);
			ZonedDateTime atStartOfDay = parse.atStartOfDay(ZoneId.systemDefault());
			return Date.from(atStartOfDay.toInstant());
		}
	}

	public static void test() {

		// LocalDate d = LocalDate.now();
		// System.out.println(d);

		// LocalDate d2 = d.plusDays(-1);

		// System.out.println(d2);

		// LocalDate d3 = d.plusMonths(-1);
		// System.out.println(d3);

		// LocalDate d4 = d.plusYears(-1);
		// System.out.println(d4);

		// final LocalDate d1 = LocalDate.now();
		// final LocalDate d2 = LocalDate.now().plusDays(20);
		// Period between = Period.between(d1, d2);
		// int days = between.getDays();
		// System.out.println(days);
		 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		 LocalDateTime parse = LocalDateTime.parse("2022-03-25 09:40:28", formatter);
		 System.out.println(parse);
		 

//		LocalDate date = LocalDate.of(2022, 9, 40);// 2014-03-18
//		int year = date.getYear();// 2014
//		Month month = date.getMonth();// MARCH
//		int day = date.getDayOfMonth();// 18
//		DayOfWeek dow = date.getDayOfWeek();// TUESDAY
//		int len = date.lengthOfMonth();// 31(鏉╂瑤閲滈張鍫熸箒婢舵艾鐨径锟�)
//		boolean leap = date.isLeapYear();// false(閺勵垯绗夐弰顖炴８楠烇拷)
//
//		date = LocalDate.of(2020, 2, 22);
//
//		len = date.lengthOfMonth();

//		System.out.println(len);
	}

	public Map<Integer,Integer> getMonthDays(){
		Map<Integer,Integer> map = new HashMap<>();
		map.put(1,31);
		int year = LocalDate.now().getYear();
		if(year%400==0||(year%4==0 && year%100!=0)){
			map.put(2,29);
		}else{
			map.put(2,28);
		}
		map.put(3,31);
		map.put(4,30);
		map.put(5,31);
		map.put(6,30);
		map.put(7,31);
		map.put(8,31);
		map.put(9,30);
		map.put(10,31);
		map.put(11,30);
		map.put(12,31);
		return map;
	}
}